<!doctype html>
<meta charset="utf-8">
<title>CSS Container Queries Test: query container for Shadow DOM</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#query-container">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
  #ancestor-across-root,
  #ancestor-skip-slotting,
  #ancestor-slotted,
  #ancestor-host,
  #ancestor-part,
  #ancestor-slotted-before,
  #ancestor-host-before,
  #ancestor-part-before,
  #ancestor-inner-part,
  #ancestor-slot-fallback,
  #inner-scope-host-part {
    width: 400px;
    container-type: inline-size;
  }
</style>

<div id="ancestor-across-root">
  <div>
    <template shadowrootmode="open">
      <style>
        @container (width = 400px) {
          #t1 { color: green; }
        }
      </style>
      <div id="t1"></div>
    </template>
  </div>
</div>

<div id="ancestor-skip-slotting">
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
      </style>
      <div>
        <slot></slot>
      </div>
    </template>
    <style>
      @container (width = 200px) {
        #t2 { color: green; }
      }
    </style>
    <div id="t2"></div>
  </div>
</div>

<div id="ancestor-slotted">
  <div>
    <template shadowrootmode="open">
      <style>
        slot {
          display: block;
          width: 200px;
          container-type: inline-size;
        }
        @container (width = 200px) {
          ::slotted(#t3) { color: green; }
        }
      </style>
      <slot></slot>
    </template>
    <div id="t3"></div>
  </div>
</div>

<div id="ancestor-host">
  <div id="t4">
    <template shadowrootmode="open">
      <style>
        @container (width = 400px) {
          :host(#t4) { color: green; }
        }
      </style>
    </template>
  </div>
</div>

<div id="ancestor-part">
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
      </style>
      <div>
        <span id="t5" part="part"></span>
      </div>
    </template>
    <style>
      @container (width = 200px) {
        #ancestor-part > div::part(part) { color: green; }
      }
    </style>
  </div>
</div>

<div id="ancestor-slotted-before">
  <div>
    <template shadowrootmode="open">
      <style>
        slot {
          display: block;
          width: 200px;
          container-type: inline-size;
        }
        @container (width = 400px) {
          ::slotted(#t6)::before {
            content: "X";
            color: green;
          }
        }
      </style>
      <slot></slot>
    </template>
    <style>
      #t6 {
        width: 400px;
        container-type: inline-size;
      }
    </style>
    <div id="t6"></div>
  </div>
</div>

<div id="ancestor-host-before">
  <div id="t7">
    <template shadowrootmode="open">
      <style>
        :host {
          width: 200px;
          container-type: inline-size;
        }
        @container (width = 200px) {
          :host(#t7)::before {
            content: "X";
            color: green;
          }
        }
      </style>
    </template>
  </div>
</div>

<div id="ancestor-part-before">
  <style>
    @container (width = 200px) {
      #ancestor-part-before > div::part(part)::before {
        content: "X";
        color: green;
      }
    }
  </style>
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
      </style>
      <div>
        <span id="t8" part="part"></span>
      </div>
    </template>
  </div>
</div>

<div id="ancestor-inner-part">
  <style>
    @container (width = 200px) {
      #ancestor-inner-part > div::part(inner-part) { color: green; }
    }
  </style>
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
      </style>
      <div exportparts="inner-part">
        <template shadowrootmode="open">
          <style>
            div {
              width: 200px;
              container-type: inline-size;
            }
          </style>
          <div>
            <span id="t9" part="inner-part"></span>
          </div>
        </template>
      </div>
    </template>
  </div>
</div>

<div id="ancestor-slot-fallback">
  <div><template shadowrootmode="open">
    <style>
      div {
        width: 200px;
        container-type: inline-size;
      }
      @container (width = 200px) {
        #t10 { color: green; }
      }
    </style>
    <div>
      <slot><span id="t10"></span></slot>
    </div>
  </template></div>
</div>

<div id="no-container-for-part">
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
        #t11 { color: red; }
      </style>
      <div>
        <span id="t11" part="part"></span>
      </div>
    </template>
    <style>
      @container (width = 200px) {
        #no-container-for-part > div::part(part) { color: green; }
      }
    </style>
  </div>
</div>

<div id="inner-scope-host-part">
  <div>
    <template shadowrootmode="open">
      <style>
        div {
          width: 200px;
          container-type: inline-size;
        }
        @container (width = 200px) {
          :host::part(part) { color: green; }
        }
      </style>
      <div>
        <span id="t12" part="part"></span>
      </div>
    </template>
  </div>
</div>

<div id="named-part-host">
  <template shadowrootmode="open">
    <style>
      @container --part2 (width >= 0px) {
        #named-part2-child { color: green; }
      }
      #named-part1 {
        container: --part1 / inline-size;
        color: green;
      }
    </style>
    <div id="named-part1" part="part1">
      <div id="named-part1-child" part="part1-child"></div>
    </div>
    <div part="part2">
      <div id="named-part2-child" part="part2-child"></div>
    </div>
  </template>
  <style>
    #named-part-host::part(part2) { container: --part2 / inline-size; }
    @container --part1 (width >= 0px) {
      #named-part-host::part(part1-child) { background-color: red; }
    }
  </style>
</div>

<div id="named-slotted-host">
  <template shadowrootmode="open">
    <style>
      @container --slot-container (width >= 0px) {
        ::slotted(#slotted1) { color: green; }
      }
      #named-slotted-container {
        container: --slot-container / inline-size;
      }
    </style>
    <div id="named-slotted-container">
      <slot></slot>
    </div>
  </template>
  <div id="slotted1"></div>
  <div id="slotted2"></div>
  <style>
    @container --slot-container (width >= 0px) {
      #slotted2 { color: red; }
    }
  </style>
</div>

<div id="named-host">
  <template shadowrootmode="open">
    <style>
      :host {
        container: --host-container / inline-size;
      }
      @container --host-container (width >= 0px) {
        #host-descendant { color: green; }
        ::slotted(#host-slotted1) { color: green; }
      }
    </style>
    <div id="host-descendant"></div>
    <slot></slot>
  </template>
  <div id="host-slotted1"></div>
  <div id="host-slotted2"></div>
  <style>
    @container --host-container (width >= 0px) {
      #host-slotted2 { color: red; }
    }
  </style>
</div>

<script>
  setup(() => {
    assert_implements_container_queries();
  });

  const green = "rgb(0, 128, 0)";
  const red = "rgb(255, 0, 0)";

  test(() => {
    const t1 = document.querySelector("#ancestor-across-root > div").shadowRoot.querySelector("#t1");
    assert_equals(getComputedStyle(t1).color, green);
  }, "Match container in outer tree");

  test(() => {
    const t2 = document.querySelector("#t2");
    assert_equals(getComputedStyle(t2).color, green);
  }, "Match container in walking flat tree ancestors");

  test(() => {
    const t3 = document.querySelector("#t3");
    assert_equals(getComputedStyle(t3).color, green);
  }, "Match container in ::slotted selector's originating element tree");

  test(() => {
    const t4 = document.querySelector("#t4");
    assert_equals(getComputedStyle(t4).color, green);
  }, "Match container in outer tree for :host");

  test(() => {
    const t5 = document.querySelector("#ancestor-part > div").shadowRoot.querySelector("#t5");
    assert_equals(getComputedStyle(t5).color, green);
  }, "Match container in ::part selector's originating element tree");

  test(() => {
    const t6 = document.querySelector("#t6");
    assert_equals(getComputedStyle(t6, "::before").color, green);
  }, "Match container for ::before in ::slotted selector's originating element tree");

  test(() => {
    const t7 = document.querySelector("#t7");
    assert_equals(getComputedStyle(t7, "::before").color, green);
  }, "Match container in outer tree for :host::before");

  test(() => {
    const t8 = document.querySelector("#ancestor-part-before > div").shadowRoot.querySelector("#t8");
    assert_equals(getComputedStyle(t8, "::before").color, green);
  }, "Match container for ::before in ::part selector's originating element tree");

  test(() => {
    const outerhost = document.querySelector("#ancestor-inner-part > div");
    const innerhost = outerhost.shadowRoot.querySelector("div");
    const t9 = innerhost.shadowRoot.querySelector("#t9");
    assert_equals(getComputedStyle(t9).color, green);
  }, "Match container for ::part selector's originating element tree for exportparts");

  test(() => {
    const t10 = document.querySelector("#ancestor-slot-fallback > div").shadowRoot.querySelector("#t10");
    assert_equals(getComputedStyle(t10).color, green);
  }, "Match container for slot light tree child fallback");

  test(() => {
    const t11 = document.querySelector("#no-container-for-part > div").shadowRoot.querySelector("#t11");
    assert_equals(getComputedStyle(t11).color, green);
  }, "Should not match container inside shadow tree for ::part()");

  test(() => {
    const t12 = document.querySelector("#inner-scope-host-part > div").shadowRoot.querySelector("#t12");
    assert_equals(getComputedStyle(t12).color, green);
  }, "A :host::part rule should match containers in the originating element tree");

  test(() => {
    const target = document.querySelector("#named-part-host").shadowRoot.querySelector("#named-part1-child");
    assert_equals(getComputedStyle(target).color, green);
  }, "Container name set inside a shadow tree should not match query using ::part on the outside");

  test(() => {
    const target = document.querySelector("#named-part-host").shadowRoot.querySelector("#named-part2-child");
    assert_equals(getComputedStyle(target).color, green);
  }, "Container name set with a ::part should match query inside the shadow tree");

  test(() => {
    const target = document.querySelector("#slotted1");
    assert_equals(getComputedStyle(target).color, green);
  }, "Container name set inside a shadow tree should match query for a ::slotted() rule inside the tree");

  test(() => {
    const target = document.querySelector("#slotted2");
    assert_not_equals(getComputedStyle(target).color, red);
  }, "Container name set inside a shadow tree should not match query for host child on the outside");

  test(() => {
    const target = document.querySelector("#named-host").shadowRoot.querySelector("#host-descendant");
    assert_equals(getComputedStyle(target).color, green);
  }, "Container name set on :host from inside a shadow tree matching query inside the shadow tree");

  test(() => {
    const target = document.querySelector("#host-slotted1");
    assert_equals(getComputedStyle(target).color, green);
  }, "Container name set on :host from inside a shadow tree matching query for ::slotted inside the shadow tree");

  test(() => {
    const target = document.querySelector("#host-slotted2");
    assert_not_equals(getComputedStyle(target).color, red);
  }, "Container name set on :host from inside a shadow tree not matching query for slotted from the outside of the shadow tree");

</script>
